/**
 * Octopus, an XMMS2 client.
 * Copyright (C) 2014 Octopus Team
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

namespace OctopusUi {
	public class UiMain : Gtk.Window {
		private Octopus.Configure config;
		private Clutter.Stage     stage;
		private bool              isFullscreen;
		private UiMedialibPanel   medialibPanel; 
		private IKeyFocusActor    keyFocusActor;

		public bool use_texture_cache { get; set; default = false; }

		public UiMain () {
			Object();
		}

		construct {
			this.set_title ("Octopus");
			this.set_default_size (1024, 768);
			//stage
			var clutterEmbed = new GtkClutter.Embed ();
			this.add (clutterEmbed);
			clutterEmbed.show ();
			this.stage = (Clutter.Stage)clutterEmbed.get_stage ();
			OctopusMx.MxTracklist.set_stage (this.stage);
			//load config
			//this.config = new Octopus.Configure ();
			this.config = Octopus.Global.get ().get_configure ();
			int window_width = 1024; //min. width
			int window_height = 768; //min. height
			if (this.config.has_key ("ui", "width")) {
				window_width =  this.config.get_integer("ui", "width");
			}
			if (this.config.has_key("ui", "height")) {
				window_height = this.config.get_integer("ui", "height");
			}
			//if (window_width >= 1024 && window_height >= 768) {
				this.resize(window_width, window_height);
			//}
			//icon
			try {
				var iconfile = GLib.Path.build_filename (Octopus.Global.get ().data_path, "octopus-48.png");
				this.icon =  new Gdk.Pixbuf.from_file (iconfile);
			} catch (GLib.Error e) {
				GLib.error ("ERROR loading application icon: %s", e.message);
			}
			//css
			try {
				//requires mx-css file at index 0
				Mx.Style.get_default ().load_from_file (Octopus.Global.get ().css_files_get (0));
			} catch (GLib.Error e) {
				GLib.error ("ERROR loading css file: %s", e.message);
			}
			var provider = new Gtk.CssProvider ();
			var display = Gdk.Display.get_default ();
			var screen = display.get_default_screen ();
			Gtk.StyleContext.add_provider_for_screen (screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
			try {
				//requires gtk-css file at index 1
				provider.load_from_path (Octopus.Global.get ().css_files_get (1));
			} catch (GLib.Error e) {
				GLib.error ("ERROR loading css file: %s", e.message);
			}
			//key-events
			this.key_press_event.connect (on_key_press_event);
			//window state
			this.window_state_event.connect (on_window_state_event);

			this.destroy.connect (() => {
				//save config
				this.config.set_integer("ui", "width", (int)this.stage.width);
				this.config.set_integer("ui", "height", (int)this.stage.height);
				this.config.save ();
				//quit main-loop
				Gtk.main_quit ();
			});

			var stageStack = new Mx.Stack ();
			stageStack.name = "stage-background";
			stageStack.width = this.stage.width;
			stageStack.height = this.stage.height;
			this.stage.add_child (stageStack);
			this.stage.notify["allocation"].connect (() => {
				stageStack.set_width (this.stage.width);
				stageStack.set_height (this.stage.height);
			});

			//medialibPanel
			var medialibPanelFrame = new Mx.Frame ();
			medialibPanelFrame.x_align = Clutter.ActorAlign.FILL;
			medialibPanelFrame.y_align = Clutter.ActorAlign.FILL;
			stageStack.add_child (medialibPanelFrame);
			this.medialibPanel = new UiMedialibPanel ();
			this.medialibPanel.use_texture_cache = this.use_texture_cache;
			medialibPanelFrame.add_child (medialibPanel);
			this.keyFocusActor = medialibPanel.keyFocusActor;
			//bottomPanel
			var bottomPanelFrame = new Mx.Frame ();
			bottomPanelFrame.x_align = Clutter.ActorAlign.FILL;
			bottomPanelFrame.y_align = Clutter.ActorAlign.END;
			stageStack.add_child (bottomPanelFrame);
			var bottomPanel = new UiBottomPanel ();
			bottomPanelFrame.add_child (bottomPanel);
			//playlistPanel
			var playlistPanelFrame = new Mx.Frame ();
			playlistPanelFrame.x_align = Clutter.ActorAlign.END;
			playlistPanelFrame.y_align = Clutter.ActorAlign.FILL;
			stageStack.add_child (playlistPanelFrame);
			var playlistPanel = new UiPlaylistPanel ();
			playlistPanel.use_texture_cache = this.use_texture_cache;
			playlistPanelFrame.add_child (playlistPanel);
			//loadscreen
			var loadscreen = new UiLoadscreen ();
			stageStack.add_child (loadscreen);
			medialibPanel.load_finished.connect (() => {
				loadscreen.visible = false;
			});

			//global signals
			Octopus.Global.get ().message.connect ((message) => {
				bottomPanel.setText (message);
			});
			//medialibPanel signals
			medialibPanel.key_focus.connect (() => {
				this.keyFocusActor = medialibPanel.keyFocusActor;
			});
			medialibPanel.show_message_bar_text.connect ((message) => {
				bottomPanel.setText (message);
			});
			//bottomPanel signals
			bottomPanel.refresh_album_list.connect (() => {
				refresh ();
			});
			bottomPanel.toggle_fullscreen.connect (() => {
				if (isFullscreen)
					this.unfullscreen ();
				else
					this.fullscreen ();
			});
			bottomPanel.quit.connect (() => {
				destroy ();
			});
			bottomPanel.layout.connect ((layout_enum) => {
				this.config.set_integer("ui", "layout", layout_enum);
				if (layout_enum == LayoutEnum.GRID) {
					medialibPanel.browsePanel.layout = LayoutEnum.GRID;
				}
				if (layout_enum == LayoutEnum.DEFORMED) {
					medialibPanel.browsePanel.layout = LayoutEnum.DEFORMED;
				}
				medialibPanel.browsePanel.load ();
			});
			bottomPanel.css.connect ((css_file) => {
				this.config.set_string ("ui", "css", css_file);
				GLib.debug ("STYLE %s", css_file);
			});
			//playlistPanel signals
			playlistPanel.key_focus.connect (() => {
				this.keyFocusActor = playlistPanel;
			});
			playlistPanel.show_message_bar_text.connect ((message) => {
				bottomPanel.setText (message);
			});

			medialibPanel.load ();
		}

		private bool on_key_press_event (Gdk.EventKey event) {
			//Ctrl + f
			if (   (event.keyval == Gdk.Key.f)
				&& ((event.state & Gdk.ModifierType.CONTROL_MASK) == Gdk.ModifierType.CONTROL_MASK)) {
				if (isFullscreen)
					this.unfullscreen ();
				else
					this.fullscreen ();
			}
			//F5 - Refresh
			else if (event.keyval == Gdk.Key.F5) {
				refresh ();
			}
			//Escape
			else if (event.keyval == Gdk.Key.Escape) {
				if (this.medialibPanel.tracklistPanelFrame.get_n_children () > 0) {
					((UiTracklistPanel)this.medialibPanel.tracklistPanelFrame.get_child_at_index (0)).tracklist_panel_close ();
				} else if (this.medialibPanel.browsePanel.browsePanelSearchStack.visible) {
					this.medialibPanel.browsePanel.browsePanelSearchEntryClose ();
				} else if (this.isFullscreen) {
					this.unfullscreen ();
				}
			}
			else {
				this.keyFocusActor.onKeyPressEvent (event);
			}
			return false; //propagate
		}

		private bool on_window_state_event (Gdk.EventWindowState event) {
			GLib.debug ("event.new_window_state  %u", event.new_window_state);
			if ((event.new_window_state & Gdk.WindowState.FULLSCREEN) == Gdk.WindowState.FULLSCREEN) {
				GLib.debug ("WindowStateManager: fullscreen ON");
				this.isFullscreen = true;
			} else {
				GLib.debug ("WindowStateManager: fullscreen OFF");
				this.isFullscreen = false;
			}
			return false; //propagate
		}

		private void refresh () {
			if (this.medialibPanel.tracklistPanelFrame.get_n_children () > 0) {
				this.medialibPanel.tracklistPanelFrame.get_child_at_index (0).destroy ();
			}
			this.medialibPanel.load ();
		}
	}

	public interface IKeyFocusActor : Object  {
		public abstract void onKeyPressEvent (Gdk.EventKey event);
		public signal void key_focus ();
	}
}
